package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.sc.nft.config.fulu.model.dto.FuLuOrderDirectDTO;
import com.sc.nft.config.fulu.model.request.FuLuOrderDirectRequest;
import com.sc.nft.config.hf.HfConfig;
import com.sc.nft.config.lianlian.LlConfig;
import com.sc.nft.config.sand.SandConfig;
import com.sc.nft.config.sand.SandPayUtil;
import com.sc.nft.dao.IdcardInfoDao;
import com.sc.nft.dao.MallOrderIncomeDao;
import com.sc.nft.dao.StaticDataDao;
import com.sc.nft.dao.UserBankCardDao;
import com.sc.nft.dao.UserCouponsDao;
import com.sc.nft.dao.UserInfoDao;
import com.sc.nft.dao.WxMiniUserInfoDao;
import com.sc.nft.dto.BindPaySendSmsVO;
import com.sc.nft.dto.MallOrderPushDTO;
import com.sc.nft.entity.ApiOrderDirect;
import com.sc.nft.entity.IdcardInfo;
import com.sc.nft.entity.MallActivityShare;
import com.sc.nft.entity.MallActivityShareTeam;
import com.sc.nft.entity.MallOrder;
import com.sc.nft.entity.MallOrderIncome;
import com.sc.nft.entity.MallOrderProduct;
import com.sc.nft.entity.MallOrderRefund;
import com.sc.nft.entity.MallOrderStatusLog;
import com.sc.nft.entity.MallPayOrderRecord;
import com.sc.nft.entity.MallProduct;
import com.sc.nft.entity.MallShareTeamOrder;
import com.sc.nft.entity.UserBankCard;
import com.sc.nft.entity.UserCoupons;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.UserWallet;
import com.sc.nft.entity.WxMiniUserInfo;
import com.sc.nft.entity.vo.BalanceVO;
import com.sc.nft.entity.vo.GetPaySignVO;
import com.sc.nft.entity.vo.mall.MallWalletPayVO;
import com.sc.nft.enums.CouponsTypeEnum;
import com.sc.nft.enums.MallOrderIncomeTypeEnum;
import com.sc.nft.enums.MallOrderPushTypeEnum;
import com.sc.nft.enums.MallOrderRefundTypeEnum;
import com.sc.nft.enums.MallOrderStatusEnum;
import com.sc.nft.enums.MallRefundStatusEnum;
import com.sc.nft.enums.PayChannelEnum;
import com.sc.nft.enums.PayMethodEnum;
import com.sc.nft.enums.PayStatusEnum;
import com.sc.nft.enums.PayTypeEnum;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.enums.SourceEnum;
import com.sc.nft.enums.UserBalanceTypeEnum;
import com.sc.nft.enums.WalletDetailTypeEnum;
import com.sc.nft.exception.GlobalException;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.feign.WxMiniUserPointsClient;
import com.sc.nft.helper.FuLuHelper;
import com.sc.nft.helper.HfPayHelper;
import com.sc.nft.helper.LlPayHelper;
import com.sc.nft.helper.MessageQueueHelper;
import com.sc.nft.helper.SandAccountHelper;
import com.sc.nft.helper.SmartSupplyHelper;
import com.sc.nft.req.points.PointsReq;
import com.sc.nft.service.ApiOrderDirectService;
import com.sc.nft.service.MallActivityShareService;
import com.sc.nft.service.MallActivityShareTeamService;
import com.sc.nft.service.MallActivitySpecsService;
import com.sc.nft.service.MallOrderIncomeService;
import com.sc.nft.service.MallOrderProductService;
import com.sc.nft.service.MallOrderPushService;
import com.sc.nft.service.MallOrderRefundService;
import com.sc.nft.service.MallOrderRefundStatusLogService;
import com.sc.nft.service.MallOrderService;
import com.sc.nft.service.MallPayOrderRecordService;
import com.sc.nft.service.MallPayOrderService;
import com.sc.nft.service.MallProductService;
import com.sc.nft.service.MallShareTeamOrderService;
import com.sc.nft.service.MallUserActivityRankingDetailService;
import com.sc.nft.service.MallUserPropsRewardsDetailService;
import com.sc.nft.service.UserWalletService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.util.BigDecimalUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static com.sc.nft.config.sand.SandPayUtil.*;


@Slf4j
@Service
@RequiredArgsConstructor
public class MallPayOrderServiceImpl implements MallPayOrderService {

    private final static String dateTimeFormat = "yyyyMMddHHmmss";
    private final MallOrderService mallOrderService;
    private final IdcardInfoDao idcardInfoDao;
    private final MallPayOrderRecordService mallPayOrderRecordService;
    private final UserWalletService userWalletService;
    private final MallOrderProductService mallOrderProductService;
    private final MallOrderIncomeService mallOrderIncomeService;
    private final MallActivitySpecsService mallActivitySpecsService;
    private final UserBankCardDao userBankCardDao;
    private final Redisson redisson;
    private final UserInfoDao userInfoDao;
    private final HfPayHelper hfPayHelper;
    private final MallOrderIncomeDao mallOrderIncomeDao;
    private final SmartSupplyHelper smartSupplyHelper;
    private final LlPayHelper llPayHelper;
    private final SandAccountHelper sandAccountHelper;
    private final FuLuHelper fuLuHelper;
    private final ApiOrderDirectService apiOrderDirectService;
    private final MallOrderRefundService mallOrderRefundService;
    private final MallOrderRefundStatusLogService mallOrderRefundStatusLogService;
    private final MallShareTeamOrderService mallShareTeamOrderService;
    private final MallActivityShareService mallActivityShareService;
    private final MallActivityShareTeamService mallActivityShareTeamService;
    private final MessageQueueHelper messageQueueHelper;
    private final StaticDataDao staticDataDao;
    private final UserCouponsDao userCouponsDao;
    private final WxMiniUserPointsClient wxMiniUserPointsClient;
    private final WxMiniUserInfoDao wxMiniUserInfoDao;
    private final MallOrderPushService mallOrderPushService;
    private final MallProductService mallProductService;
    private final MallUserActivityRankingDetailService mallUserActivityRankingDetailService;
    private final MallUserPropsRewardsDetailService mallUserPropsRewardsDetailService;
    @Value("${pay.wallet.wallet_url}")
    private String walletUrl;
    @Value("${pay.url.mallPaySuccessReturnUrl}")
    private String mallPaySuccessReturnUrl;
    @Value("${pay.hfConfig.mallFrontReturnUrl}")
    private String mallFrontReturnUrl;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MallWalletPayVO mallWalletPay(PayMethodEnum paymentMethod, Long orderId, UserInfo user, String ip) {
        DateTime now = DateTime.now();
        MallOrder mallOrder = mallOrderService.getById(orderId);
        //1.校验订单
        checkPayOrder(mallOrder, user);
        //1.1校验支付金额是否为0为零时不要判断余额是否充足
        if (BigDecimalUtils.compare(mallOrder.getRealPrice(), BigDecimal.ZERO)) {

            UserWallet userWallet = userWalletService.getByUserId(user.getId());
            //提现余额
            BigDecimal balance = userWallet.getBalance();
            //支付余额
            BigDecimal payBalance = userWallet.getPayBalance();
            //购物金
            BigDecimal wishBalance = userWallet.getWishBalance();
            BigDecimal realPrice = mallOrder.getRealPrice();
            mallOrder.setPayBalancePrice(BigDecimal.ZERO);
            mallOrder.setPayWalletPrice(BigDecimal.ZERO);
            mallOrder.setPayPrice(realPrice);
            // 生态爆品
            String zoologyActivityIds = staticDataDao.getByType("zoology_activity_ids").getValue();
            List<Long> ids = JSONArray.parseArray(zoologyActivityIds, Long.class);
            List<MallOrderProduct> listByOrderId = mallOrderProductService.getListByOrderId(mallOrder.getId());
            Boolean isHave = false;
            for (MallOrderProduct mallOrderProduct : listByOrderId) {
                if (ids.contains(mallOrderProduct.getActivityId())) {
                    isHave = true;
                } else {
                    MallProduct mallProduct = mallProductService.getById(mallOrderProduct.getProductId());
                    if (!mallProduct.isAllowedShoppingCoupons()) {
                        isHave = true;
                    }
                }

            }
            //特殊活动或者不支持购物金则将购物金置为0
            if (isHave || !mallOrder.getIsAllowedShoppingCoupons()) {
                wishBalance = BigDecimal.ZERO;
            }
            BigDecimal sumBalance = balance.add(payBalance).add(wishBalance);
            //校验余额是否足够
            Assert.isFalse(realPrice.compareTo(sumBalance) == 1, () -> new GlobalRunTimeException(ErrorCode.BALANCE_NO_ENOUGH));
            BigDecimal lastPrice = realPrice;
            if (NumberUtil.isGreater(wishBalance, BigDecimal.ZERO)) {
                BigDecimal payPrice = NumberUtil.min(wishBalance, lastPrice);
                Assert.isTrue(userWalletService.subBalance(userWallet, payPrice, orderId, WalletDetailTypeEnum.IP_CONSUMPTION, UserBalanceTypeEnum.WISH_BALANCE), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                mallOrder.setWishBalancePrice(payPrice);
                lastPrice = lastPrice.subtract(payPrice);
            }
            if (NumberUtil.isGreater(lastPrice, BigDecimal.ZERO) && NumberUtil.isGreater(payBalance, BigDecimal.ZERO)) {
                BigDecimal payPrice = NumberUtil.min(payBalance, lastPrice);
                Assert.isTrue(userWalletService.subBalance(userWallet, payPrice, orderId, WalletDetailTypeEnum.IP_CONSUMPTION, UserBalanceTypeEnum.PAY_BALANCE), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                mallOrder.setPayBalancePrice(payPrice);
                lastPrice = lastPrice.subtract(payPrice);

            }
            if (NumberUtil.isGreater(lastPrice, BigDecimal.ZERO) && NumberUtil.isGreaterOrEqual(balance, lastPrice)) {
                Assert.isTrue(userWalletService.subBalance(userWallet, lastPrice, orderId, WalletDetailTypeEnum.IP_CONSUMPTION, UserBalanceTypeEnum.BALANCE), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                mallOrder.setPayWalletPrice(lastPrice);
            }
        }

        //3.更新订单状态
        mallOrder.setPayTime(DateTime.now());
        mallOrder.setPayType(paymentMethod);
        mallOrder.updateById();
        if (StrUtil.isNotBlank(mallOrder.getSupplyOrderNo())) {
            smartSupplyHelper.confirmOrder(mallOrder);
        }
        //更新订单状态
        if (mallOrder.getIsVirtual()) {
            mallOrderService.updateStatusById(mallOrder.getId(), MallOrderStatusEnum.FINISH);
        } else {
            mallOrderService.updateStatusById(mallOrder.getId(), MallOrderStatusEnum.WAIT_RECEIPT);
        }
        //获取订单商品
        List<MallOrderProduct> orderProductList = mallOrderProductService.getListByOrderId(mallOrder.getId());
        for (MallOrderProduct mallOrderProduct : orderProductList) {
            //4.扣除库存
            Assert.isTrue(mallActivitySpecsService.frozenConsumeStockByIdAndCount(mallOrderProduct.getActivitySpecsId(), mallOrderProduct.getProductNum()), () -> new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER));
        }

        //是否使用了折扣券，如果使用的折扣券也不计算收益
        UserCoupons userCoupons = userCouponsDao.getByOrderId(mallOrder.getId());
        boolean proportionCoupon = Optional.ofNullable(userCoupons).isPresent() && userCoupons.getCouponsType().getType().equals(CouponsTypeEnum.DISCOUNT_PROPORTION_COUPON.getType());
        //判断支付金额为0时是否计算收益
        if (!mallOrder.getIsVirtual() && BigDecimalUtils.compare(mallOrder.getRealPrice(), BigDecimal.ZERO) && !proportionCoupon) {
            mallOrderIncomeService.newCalCulateIncome(orderProductList, mallOrder, user);
            if (Objects.nonNull(mallOrder.getShareTeamId())) {
                mallShareTeamOrderService.create(mallOrder.getShareTeamId(), mallOrder);
            }
        }
//        if (!user.getIsValid()) {
//            userInfoDao.setIsValid(user.getId());
//        }

        //5.添加支付记录
        MallPayOrderRecord mallPayOrderRecord = new MallPayOrderRecord();
        mallPayOrderRecord.setUserId(user.getId());
        mallPayOrderRecord.setPayType(paymentMethod);
        mallPayOrderRecord.setReqTime(now);
        mallPayOrderRecord.setCloseTime(DateTime.now());
        mallPayOrderRecord.setOrderNo(mallOrder.getOrderNo());
        mallPayOrderRecord.setReqIp(ip);
        mallPayOrderRecord.setOrderType(PayTypeEnum.PAY);
        mallPayOrderRecord.setPayAmount(mallOrder.getRealPrice());
        mallPayOrderRecord.setRefundAmount(BigDecimal.ZERO);
        mallPayOrderRecord.setNotifyUrl(StrUtil.EMPTY);
        mallPayOrderRecord.setFrontUrl(StrUtil.EMPTY);
        mallPayOrderRecord.setOutTradeNo(StrUtil.EMPTY);
        mallPayOrderRecord.setTradeNo(StrUtil.EMPTY);
        mallPayOrderRecord.setChannel(PayChannelEnum.NATIVE);
        mallPayOrderRecord.setReqResult(StrUtil.EMPTY);
        mallPayOrderRecord.setStatus(PayStatusEnum.SUCCESS);
        mallPayOrderRecord.setPayResult(StrUtil.EMPTY);
        mallPayOrderRecord.setPayTime(DateTime.now());
        mallPayOrderRecord.insert();
        if (mallOrder.getIsVirtual()) {
            // 为虚拟商品订单
            ApiOrderDirect apiOrderDirect = apiOrderDirectService.getByOrderId(mallOrder.getId());
            if (Objects.nonNull(apiOrderDirect)) {
                try {
                    // 直充下单
                    FuLuOrderDirectDTO fuLuOrderDirectDTO = fuLuHelper.fuLuOrderDirect(FuLuOrderDirectRequest.build(apiOrderDirect.getApiProductId(), apiOrderDirect.getOrderNo(), apiOrderDirect.getApiChargeAccount(), apiOrderDirect.getApiBuyNum()));
                    if (Objects.nonNull(fuLuOrderDirectDTO)) {
                        apiOrderDirect.setApiOrderId(fuLuOrderDirectDTO.getOrderId());
                        apiOrderDirect.setApiOrderState(fuLuOrderDirectDTO.getOrderState());
                        apiOrderDirect.setApiProductName(fuLuOrderDirectDTO.getProductName());
                        apiOrderDirect.updateById();
                    }
                } catch (Exception e) {
                    log.info("直充下单异常:{}", e.getMessage());
                }
            }
        }
        if (mallOrder.getActivityType() == com.sc.nft.enums.task.ActivityTypeEnum.SALES && !mallOrder.getIsVirtual()) {
            //更新排行榜数据
            try {
                BigDecimal consumptionAmount = mallOrder.getPayPrice().subtract(mallOrder.getWishBalancePrice());
                if (consumptionAmount.compareTo(BigDecimal.ZERO) > 0) {
                    mallUserActivityRankingDetailService.saveOrUpdate(mallOrder.getUserId(), null, consumptionAmount, mallOrder.getPayTime());
                    //道具释放活动
                    mallUserPropsRewardsDetailService.payScuuess(user.getId(), mallOrder.getDaoId(), orderProductList, consumptionAmount, mallOrder.getOrderNo(), mallOrder.getTotalNum());
                }
            } catch (Exception e) {
                log.error("ranking detail save or update error", e);
            }
        }
        MallWalletPayVO mallWalletPayVO = new MallWalletPayVO();
        mallWalletPayVO.setId(mallOrder.getId());
        mallWalletPayVO.setPayNotify(Boolean.TRUE);
        return mallWalletPayVO;
    }

    @Override
    public Long sandMallBindPaySendSms(Long bankCardId, Long orderId, UserInfo userInfo, String IP) {
        MallOrder order = mallOrderService.getById(orderId);
        //1.校验订单
        checkPayOrder(order, userInfo);

        UserBankCard userBankCard = userBankCardDao.getById(bankCardId);
        Assert.notNull(userBankCard, () -> new GlobalRunTimeException(ErrorCode.CARD_NOT_FOUND));
        Assert.isTrue(userBankCard.getUserId().longValue() == userInfo.getId().longValue(), () -> new GlobalRunTimeException(ErrorCode.CARD_NOT_FOUND));
        MallPayOrderRecord payOrder = new MallPayOrderRecord();
        DateTime now = DateTime.now();
        payOrder.setPayType(PayMethodEnum.FAST_PAY);
        payOrder.setReqTime(now);
        payOrder.setCloseTime(order.getExpiredTime());
        payOrder.setOrderNo(order.getOrderNo());
        payOrder.setReqIp(IP);
        payOrder.setOrderType(PayTypeEnum.PAY);
        payOrder.setPayAmount(order.getRealPrice());
        payOrder.setUserCardId(bankCardId);
        payOrder.setRefundAmount(BigDecimal.ZERO);
        payOrder.setChannel(payOrder.getPayType().getChannel());
        payOrder.setTradeNo(UUID.fastUUID().toString().replaceAll("-", ""));
        payOrder.setStatus(PayStatusEnum.INIT);
        payOrder.setNotifyUrl(SandConfig.MALL_NOTIFY_URL);
        payOrder.setFrontUrl(SandConfig.FAST_RETURN_URL);
        payOrder.setUserId(order.getUserId());
        JSONObject header = getHeader(PAY_SMS_METHOD, BIND_CARD);
        JSONObject body = getSendSmsRequest(userBankCard, userInfo, payOrder.getTradeNo());
        JSONObject result = fastPayRequest(header, body, PAY_SMS_PATH);
        payOrder.setReqResult(result.toJSONString());
        payOrder.insert();
        if (!StrUtil.equals(result.getJSONObject("head").getString("respCode"), "000000")) {
            throw new GlobalRunTimeException("发送短信失败：" + result.getJSONObject("head").getString("respMsg"));
        }
        return payOrder.getId();
    }

    @Override
    public void sandMallBindPay(Long payOrderId, String smsCode, UserInfo userInfo) {
        MallPayOrderRecord payOrder = mallPayOrderRecordService.getById(payOrderId);
        Assert.notNull(payOrder, () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));
        String title;
        if (payOrder.getOrderType() == PayTypeEnum.PAY) {
            MallOrder order = mallOrderService.getByOrderNo(payOrder.getOrderNo());
            Assert.notNull(order, () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));
            Assert.isTrue(order.getUserId().longValue() == userInfo.getId().longValue(), () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));
            Assert.isTrue(order.getStatus() == MallOrderStatusEnum.WAIT_PAY, () -> new GlobalRunTimeException(ErrorCode.ORDER_STATUS_ERROR));
            title = mallOrderProductService.getProductTitleByOrderId(order.getId());
            log.info("支付订单标题：", title);
        } else {
            throw new GlobalRunTimeException("支付订单类型不正确");
        }

        IdcardInfo idcardInfo = idcardInfoDao.getByUserIdAndIsPass(userInfo.getId());
        Assert.notNull(idcardInfo, () -> new GlobalRunTimeException(ErrorCode.USER_NOT_SM));
        UserBankCard userBankCard = userBankCardDao.getById(payOrder.getUserCardId());
        Assert.notNull(userBankCard, () -> new GlobalRunTimeException(ErrorCode.CARD_NOT_FOUND));
        Assert.isTrue(userBankCard.getUserId().longValue() == userInfo.getId().longValue(), () -> new GlobalRunTimeException(ErrorCode.CARD_NOT_FOUND));
        JSONObject header = getHeader(PAY_METHOD, BIND_CARD);
        JSONObject body = getMallFastPayRequest(payOrder, title, userBankCard, userInfo, smsCode);
        JSONObject result = fastPayRequest(header, body, PAY_PATH);
        payOrder.setReqResult(body.toJSONString());
        payOrder.setPayResult(result.toJSONString());
        payOrder.updateById();
        if (!StrUtil.equals(result.getJSONObject("head").getString("respCode"), "000000")) {
            throw new GlobalRunTimeException("支付失败:" + result.getJSONObject("head").getString("respMsg"));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paySuccess(String orderCode, Date payTime, String result, PayMethodEnum paymentMethod) throws GlobalException {
        MallPayOrderRecord payOrder = mallPayOrderRecordService.getByTradeNo(orderCode);
        log.info("支付成功回调：{}", payOrder);
        Assert.notNull(payOrder, () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));
        if (payOrder.getStatus() == PayStatusEnum.SUCCESS) {
            return;
        }
        MallOrder order = mallOrderService.getByOrderNo(payOrder.getOrderNo());
        Assert.notNull(order, () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));

        RLock lock = redisson.getLock(RedisKeyEnum.MALL_PAY_SUCCESS_LOCK.getKey() + order.getId());
        try {
            boolean res = lock.tryLock(10, 10, TimeUnit.SECONDS);

            if (res) {
                payOrder.setStatus(PayStatusEnum.SUCCESS);
                payOrder.setPayTime(payTime);
                payOrder.setPayResult(result);
                log.info("支付成功回调修改前：{}", payOrder.getStatus());
                log.info("支付成功回调修改前：{}", payOrder);
                payOrder.updateById();

                if (payOrder.getOrderType() == PayTypeEnum.PAY) {//支付
                    if (order.getStatus() != MallOrderStatusEnum.WAIT_PAY) {
                        return;
                    }
                    paySuccess(order, paymentMethod, payOrder);
                }
            }
        } catch (InterruptedException e) {
            throw new GlobalException("系统超时");
        } finally {
            lock.unlock();
        }


    }

    @Override
    public void refundSuccess(String orderCode, String payTime, String result, PayMethodEnum paymentMethod) throws GlobalException {
        MallPayOrderRecord payOrder = mallPayOrderRecordService.getByTradeNo(orderCode);
        log.info("MallPayOrderRecord:{}", JSON.toJSONString(payOrder));
        Assert.notNull(payOrder, () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));
        if (payOrder.getStatus() == PayStatusEnum.SUCCESS) {
            return;
        }
        // 获取售后单
        MallOrderRefund mallOrderRefund = mallOrderRefundService.getByNo(payOrder.getRefundNo());
        log.info("售后单:{}", JSON.toJSONString(mallOrderRefund));
        MallOrder order = mallOrderService.getByOrderNo(payOrder.getOrderNo());
        Assert.notNull(order, () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));
        Assert.notNull(mallOrderRefund, () -> new GlobalRunTimeException(ErrorCode.THE_AFTER_SALES_ORDER_DOES_NOT_EXIST));

        RLock lock = redisson.getLock(RedisKeyEnum.MALL_REFUND_SUCCESS_LOCK.getKey() + order.getId());
        try {
            boolean res = lock.tryLock(10, 10, TimeUnit.SECONDS);

            if (res) {
                payOrder.setStatus(PayStatusEnum.SUCCESS);
                payOrder.setPayTime(DateTime.of(payTime, dateTimeFormat));
                payOrder.setPayResult(result);
                payOrder.updateById();

                if (payOrder.getOrderType() == PayTypeEnum.REFUND) {
                    //退款
                    if (mallOrderRefund.getRefundStatus() != MallRefundStatusEnum.REFUNDING) {
                        return;
                    }
                    log.info("refundSuccess begin=");
                    refundSuccess(mallOrderRefund, order);
                    log.info("refundSuccess end=");
                }
            } else {
                throw new GlobalException(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            throw new GlobalException("系统超时");
        } finally {
            lock.unlock();
        }
    }


    @Override
    public GetPaySignVO getMallPay(PayMethodEnum payMethod, Long orderId, UserInfo userInfo, String IP, String mac, Boolean webPay, Integer jumpType) {
        MallOrder order = mallOrderService.getById(orderId);
        //校验订单
        checkPayOrder(order, userInfo);

        Assert.isNull(mallPayOrderRecordService.getPaySuccessByOrderNo(order.getOrderNo()), () -> new GlobalRunTimeException(ErrorCode.ORDER_PAID));
        // 杉德收银台支付的时候，不会重新发起一条，而是会直接告知错误信息订单已存在。所以要查询一下,确定是否存在,同时也要考虑是否过期的问题
        if (payMethod == PayMethodEnum.SAND_BALANCE_PAY) {
            MallPayOrderRecord byOrderNo = mallPayOrderRecordService.getPayOrderNo(order.getOrderNo());
            if (BeanUtil.isNotEmpty(byOrderNo)) {
                if (byOrderNo.getStatus() == PayStatusEnum.INIT) {
                    GetPaySignVO getPaySignVO = new GetPaySignVO();
                    getPaySignVO.setSign(byOrderNo.getReqResult());
                    getPaySignVO.setId(byOrderNo.getId());
                    getPaySignVO.setOrderNo(order.getOrderNo());
                    getPaySignVO.setPayMethodEnum(payMethod);
                    return getPaySignVO;
                } else {
                    throw new GlobalRunTimeException("订单状态异常，取消后重新下单");
                }
            }
        }
        MallPayOrderRecord payOrder = new MallPayOrderRecord();
        DateTime now = DateTime.now();
        payOrder.setPayType(payMethod);
        payOrder.setReqTime(now);
        payOrder.setCloseTime(order.getExpiredTime());
        payOrder.setOrderNo(order.getOrderNo());
        payOrder.setReqIp(IP);
        payOrder.setUserId(userInfo.getId());
        payOrder.setOrderType(PayTypeEnum.PAY);
        payOrder.setPayAmount(order.getRealPrice());
        payOrder.setRefundAmount(BigDecimal.ZERO);
        payOrder.setChannel(payMethod.getChannel());
        payOrder.setStatus(PayStatusEnum.INIT);
        payOrder.setTradeNo(UUID.fastUUID().toString().replaceAll("-", ""));
        payOrder.setUserId(order.getUserId());
        String result = null;
        String title = null;
        switch (payMethod) {
            case HF_FAST_PAY:
                payOrder.setNotifyUrl(HfConfig.mallNotifyUrl);
                if (BooleanUtil.isTrue(webPay)) {
                    StringBuffer frontUrl = new StringBuffer();
                    if (jumpType.intValue() == 1) {
                        frontUrl.append(mallFrontReturnUrl);
                    } else if (jumpType.intValue() == 2) {
                        frontUrl.append(mallPaySuccessReturnUrl);
                    }
                    frontUrl.append("?orderNo=").append(payOrder.getOrderNo()).append("&id=").append(orderId).append("&type=2");
                    payOrder.setFrontUrl(frontUrl.toString());
                } else {
                    payOrder.setFrontUrl(SandConfig.FAST_RETURN_URL);
                }

                IdcardInfo idCard = idcardInfoDao.getByUserIdAndIsPass(payOrder.getUserId());
                title = mallOrderProductService.getProductTitleByOrderId(order.getId());
                log.info("IP商城商品title:{}", title);
                JSONObject jsonObject = hfPayHelper.createMallOrder(order.getId(), payOrder, title.replaceAll(StrUtil.SPACE, ""), idCard.getCardId(), idCard.getName(), mac);
                result = jsonObject.getString("pay_url");
                payOrder.setReqResult(jsonObject.toJSONString());
                break;
            case SAND_BALANCE_PAY:
                if (!userInfo.getSandAccountOpen()) {
                    throw new GlobalRunTimeException("请先完成开户");
                }
                BalanceVO balance = sandAccountHelper.getBalance(userInfo);
                if (NumberUtil.isGreater(payOrder.getPayAmount(), new BigDecimal(balance.getAvailableBal()))) {
                    throw new GlobalRunTimeException("余额不足");
                }
                title = mallOrderProductService.getProductTitleByOrderId(order.getId());
                payOrder.setNotifyUrl(SandConfig.MALL_NOTIFY_URL);
                if (webPay) {
                    StringBuffer frontUrl = new StringBuffer();
                    if (jumpType.intValue() == 1) {
                        frontUrl.append(walletUrl);
                    } else if (jumpType.intValue() == 2) {
                        frontUrl.append(mallPaySuccessReturnUrl);
                    }

                    frontUrl.append("?orderNo=").append(payOrder.getOrderNo()).append("&id=").append(orderId).append("&type=2");
                    payOrder.setFrontUrl(frontUrl.toString());
                } else {
                    payOrder.setFrontUrl(SandConfig.FAST_RETURN_URL);
                }
                result = SandPayUtil.c2bRequest(getHeader(C2B_METHOD, C2B_PRODUCT_CODE), c2bCreateOrder(payOrder, title, userInfo), "createOrder");
                payOrder.setReqResult(result);
                break;
            default:
                throw new GlobalRunTimeException("暂不支持该支付方式");

        }
        payOrder.insert();
        GetPaySignVO getPaySignVO = new GetPaySignVO();
        getPaySignVO.setSign(result);
        getPaySignVO.setOrderNo(order.getOrderNo());
        getPaySignVO.setPayMethodEnum(payMethod);
        return getPaySignVO;
    }

    @Override
    public MallWalletPayVO getMallPayResult(String orderNo) {
        MallOrder order = mallOrderService.getByOrderNo(orderNo);
        Assert.notNull(order, () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));

        MallWalletPayVO mallWalletPayVO = new MallWalletPayVO();
        mallWalletPayVO.setId(order.getId());
        mallWalletPayVO.setPayNotify(ObjectUtil.isNotNull(mallPayOrderRecordService.getPaySuccessByOrderNo(orderNo)));
        return mallWalletPayVO;
    }

    @Override
    public BindPaySendSmsVO llBindPaySendSms(Long bankCardId, Long orderId, UserInfo userInfo, String IP) {
        MallOrder order = mallOrderService.getById(orderId);
        //校验订单
        checkPayOrder(order, userInfo);

        UserBankCard userBankCard = userBankCardDao.getById(bankCardId);
        Assert.isTrue(ObjectUtil.isNotNull(userBankCard) || userBankCard.getChannel() != PayChannelEnum.LL_PAY, () -> new GlobalRunTimeException(ErrorCode.CARD_NOT_FOUND));
        Assert.isTrue(userBankCard.getUserId().longValue() == userInfo.getId().longValue(), () -> new GlobalRunTimeException(ErrorCode.CARD_NOT_FOUND));

        Assert.isNull(mallPayOrderRecordService.getPaySuccessByOrderNo(order.getOrderNo()), () -> new GlobalRunTimeException(ErrorCode.ORDER_PAID));
        MallPayOrderRecord payOrder = new MallPayOrderRecord();
        DateTime now = DateTime.now();
        payOrder.setPayType(PayMethodEnum.LL_PAY);
        payOrder.setReqTime(now);
        payOrder.setCloseTime(order.getExpiredTime());
        payOrder.setOrderNo(order.getOrderNo());
        payOrder.setReqIp(IP);
        payOrder.setOrderType(PayTypeEnum.PAY);
        payOrder.setPayAmount(order.getRealPrice());
        payOrder.setUserCardId(bankCardId);
        payOrder.setRefundAmount(BigDecimal.ZERO);
        payOrder.setChannel(payOrder.getPayType().getChannel());
        payOrder.setTradeNo(UUID.fastUUID().toString().replaceAll("-", ""));
        payOrder.setStatus(PayStatusEnum.INIT);
        payOrder.setNotifyUrl(LlConfig.mallLlNotifyUrl);
        payOrder.setFrontUrl(SandConfig.FAST_RETURN_URL);
        payOrder.setUserId(order.getUserId());
        JSONObject createOrder = llPayHelper.createMallOrder(userInfo, payOrder);
        List<MallOrderProduct> orderProductList = mallOrderProductService.getListByOrderId(order.getId());
        JSONObject result = llPayHelper.fastMallPay(userInfo, ObjectUtil.isNull(orderProductList.get(0).getProductName()) ? "PICO 4 Pro VR 一体机" : orderProductList.get(0).getProductName(), payOrder, userBankCard);
        payOrder.setReqResult(result.toJSONString());
        payOrder.insert();

        BindPaySendSmsVO bindPaySendSmsVO = new BindPaySendSmsVO();
        bindPaySendSmsVO.setId(payOrder.getId());
        bindPaySendSmsVO.setOrderNo(payOrder.getOrderNo());
        bindPaySendSmsVO.setToken(result.getString("token"));
        return bindPaySendSmsVO;
    }

    @Override
    public void llPayVerify(UserInfo userInfo, Long id, String token, String smsCode) {
        MallPayOrderRecord payOrder = mallPayOrderRecordService.getById(id);
        Assert.isTrue(ObjectUtil.isNotNull(payOrder) || payOrder.getPayType() != PayMethodEnum.LL_PAY, () -> new GlobalRunTimeException("未找到支付订单"));
        Assert.isTrue(payOrder.getStatus() == PayStatusEnum.INIT, () -> new GlobalRunTimeException("订单已支付"));
        llPayHelper.verifySmsCode(userInfo, payOrder.getTradeNo(), payOrder.getPayAmount().setScale(2, BigDecimal.ROUND_DOWN), token, smsCode, null, payOrder.getPayType());
        log.info("tradeNo:{},payAmount:{},token:{},smsCode:{}", payOrder.getTradeNo(), payOrder.getPayAmount().setScale(2, BigDecimal.ROUND_DOWN), token, smsCode);
    }


    private void refundSuccess(MallOrderRefund mallOrderRefund, MallOrder mallOrder) {
        BigDecimal mallOrderRefundRefundAmount = mallOrderRefund.getRefundAmount();
        log.info("获取退款成功的退款金额");
        // 获取退款成功的退款金额
        List<MallOrderRefund> refundSuccessList = mallOrderRefundService.getRefundSuccessListByOrderId(mallOrder.getId());
        log.info("已成功退款数量");
        // 已成功退款数量
        Integer refundSuccessNum = refundSuccessList.stream().mapToInt(MallOrderRefund::getRefundNum).sum();
        BigDecimal refundSuccessAmount = refundSuccessList.stream().map(MallOrderRefund::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 售后单
        mallOrderRefund.setRefundStatus(MallRefundStatusEnum.REFUND_SUCCES);
        mallOrderRefund.updateById();
        // 售后单操作日志
        mallOrderRefundStatusLogService.create(mallOrderRefund.getId(), MallRefundStatusEnum.REFUND_SUCCES, "退款金额已原路退还到你的账户");
        log.info("售后单操作日志");
        //处理订单商品退款状态
        MallOrderProduct mallOrderProduct = mallOrderProductService.getById(mallOrderRefund.getOrderGoodsId());
        mallOrderProduct.setRefundSuccessCount(mallOrderProduct.getRefundSuccessCount() + mallOrderRefund.getRefundNum());
        mallOrderProduct.updateById();
        log.info("判断订单是否全部退款");
        //判断订单是否全部退款
        List<MallOrderProduct> orderProductList = mallOrderProductService.getListByOrderId(mallOrderRefund.getOrderId());
        //商品售后退款成功总数
        int sumRefundSuccessCount = orderProductList.stream().mapToInt(orderProduct -> Objects.isNull(orderProduct.getRefundSuccessCount()) ? 0 : orderProduct.getRefundSuccessCount()).sum();
        log.info("商品售后退款成功总数 sumRefundSuccessCount=" + sumRefundSuccessCount);
        //商品购买总数
        int sumProductNum = orderProductList.stream().mapToInt(orderProduct -> Objects.isNull(orderProduct.getProductNum()) ? 0 : orderProduct.getProductNum()).sum();
        log.info("商品购买总数 sumProductNum=" + sumProductNum);
        if (sumProductNum <= sumRefundSuccessCount) {
            mallOrder.setStatus(MallOrderStatusEnum.CLOSURE);
            mallOrder.updateById();
            MallOrderStatusLog mallOrderStatusLog = new MallOrderStatusLog();
            mallOrderStatusLog.setMallOrderId(mallOrder.getId());
            mallOrderStatusLog.setChangeType(MallOrderStatusEnum.CLOSURE.toString());
            mallOrderStatusLog.setChangeMessage(MallOrderStatusEnum.CLOSURE.getDescription());
            mallOrderStatusLog.setChangeMessage("交易关闭时间");
            mallOrderStatusLog.insert();
        }
        BigDecimal totalRefundSuccessAmount = BigDecimalUtils.add(refundSuccessAmount, mallOrderRefundRefundAmount);
        //收益处理
        List<MallOrderIncome> orderIncomeList = mallOrderIncomeDao.getListByOrderId(mallOrder.getId());
        if (orderIncomeList.size() > 0) {

            //如果退款金额大于等于订单金额，那么收益全部失效
            if (BigDecimalUtils.compareTo(totalRefundSuccessAmount, mallOrder.getRealPrice())) {
                for (MallOrderIncome mallOrderIncome : orderIncomeList) {
                    mallOrderIncome.setCancelIncomePrice(mallOrderIncome.getIncomeNum());
                    mallOrderIncome.setIncomeStatus(MallOrderIncomeTypeEnum.EXPIRED);
                    mallOrderIncome.setIsEfficient(Boolean.FALSE);
                    mallOrderIncome.updateById();
                }
            } else {
                Integer RefundNum = refundSuccessNum + mallOrderRefund.getRefundNum();
                //只退了一部分商品
                for (MallOrderIncome mallOrderIncome : orderIncomeList) {
                    MallOrderProduct orderProduct = mallOrderProductService.getOneByOrderIdAndOrderProductId(mallOrderRefund.getOrderId(), mallOrderRefund.getOrderGoodsId());
                    Integer productNum = orderProduct.getProductNum();
                    BigDecimal oldRealIncomePrice = mallOrderIncome.getRealIncomePrice();
                    BigDecimal realIncomePrice = BigDecimalUtils.multiplys(oldRealIncomePrice, BigDecimalUtils.divide(RefundNum, productNum));
                    BigDecimal cancelIncomePrice = oldRealIncomePrice.subtract(realIncomePrice);
                    //真实到账的收益
                    mallOrderIncome.setRealIncomePrice(realIncomePrice);
                    mallOrderIncome.setIsEfficient(Boolean.TRUE);
                    //失效的收益
                    mallOrderIncome.setCancelIncomePrice(cancelIncomePrice);
                    mallOrderIncome.updateById();
                }
            }
        }
        log.info("收益处理");
        if (SourceEnum.MINI_MALL_APP == mallOrder.getOrderSource()) {
            Long recommendedWxMiniUserId = null;
            // 计算收益
            if (Objects.nonNull(mallOrder.getRecommendedUserId())) {
                UserInfo userInfo = userInfoDao.getById(mallOrder.getUserId());
                if (Objects.nonNull(userInfo.getRecommendUserId())) {
                    WxMiniUserInfo info = wxMiniUserInfoDao.getByUserId(userInfo.getRecommendUserId());
                    if (Objects.nonNull(info)) {
                        recommendedWxMiniUserId = info.getId();
                    }
                }
            }
            // 小程序订单 扣除积分
            wxMiniUserPointsClient.subPoints(PointsReq.buildRefundSelfAndFriend(mallOrder.getMiniUserId(), recommendedWxMiniUserId, mallOrder.getId(), mallOrder.getRealPrice(), mallOrderRefund.getRefundAmount()));
        }
        log.info("小程序订单 扣除积分");
        // 拼团收益处理
        if (Objects.nonNull(mallOrder.getShareTeamId())) {
            MallShareTeamOrder mallShareTeamOrder = mallShareTeamOrderService.getByOrderId(mallOrder.getShareTeamId(), mallOrder.getId());
            if (Objects.nonNull(mallShareTeamOrder)) {
                if (BigDecimalUtils.compareTo(totalRefundSuccessAmount, mallOrder.getRealPrice())) {
                    // 全额退款
                    mallShareTeamOrder.setHeadIncome(BigDecimal.ZERO);
                    mallShareTeamOrder.setIsCanIssue(Boolean.FALSE);
                    mallShareTeamOrder.setIsIssue(Boolean.FALSE);
                    mallShareTeamOrder.updateById();
                    // 去除有效订单
                    mallActivityShareTeamService.subValidOrderNumById(mallShareTeamOrder.getActivityShareTeamId(), 1);
                } else {
                    //只退了一部分商品
                    //订单有效金额
                    BigDecimal orderValidAmount = mallOrder.getRealPrice().subtract(totalRefundSuccessAmount);
                    MallActivityShareTeam mallActivityShareTeam = mallActivityShareTeamService.getById(mallShareTeamOrder.getActivityShareTeamId());
                    MallActivityShare mallActivityShare = mallActivityShareService.getById(mallActivityShareTeam.getActivityShareId());
                    BigDecimal headIncome = orderValidAmount.multiply(mallActivityShare.getRewardPercentage());
                    mallShareTeamOrder.setHeadIncome(headIncome);
                    mallShareTeamOrder.setIsCanIssue(Boolean.TRUE);
                    mallShareTeamOrder.setIsIssue(Boolean.FALSE);
                    mallShareTeamOrder.updateById();
                }
            }
        }
        if (mallOrder.getActivityType() == com.sc.nft.enums.task.ActivityTypeEnum.SALES && !mallOrder.getIsVirtual()) {
            //更新排行榜数据
            try {
                if (totalRefundSuccessAmount.compareTo(BigDecimal.ZERO) > 0) {
                    mallUserActivityRankingDetailService.saveOrUpdate(mallOrder.getUserId(), null, totalRefundSuccessAmount.negate(), mallOrder.getPayTime());
                    if (MallOrderStatusEnum.FINISH != mallOrder.getStatus() && mallOrder.getStatus() != MallOrderStatusEnum.RECEIPT) {
                        mallUserPropsRewardsDetailService.cancel(mallOrder.getId(), totalRefundSuccessAmount);
                    }
                }
            } catch (Exception e) {
                log.error("ranking detail save or update error", e);
            }
        }
        log.info("拼团收益处理");
        //region 推送消息
        log.info("推送消息 开始");
        MallOrderPushTypeEnum mallOrderPushTypeEnum = null;
        if (MallOrderRefundTypeEnum.ONLY_REFUND == mallOrderRefund.getRefundType()) {
            mallOrderPushTypeEnum = MallOrderPushTypeEnum.ONLY_REFUND_REFUND_SUCCESS;
        } else if (MallOrderRefundTypeEnum.REFUNDS == mallOrderRefund.getRefundType()) {
            mallOrderPushTypeEnum = MallOrderPushTypeEnum.REFUNDS_REFUND_SUCCESS;
        }
        log.info("mallOrderRefund.getRefundType()=" + mallOrderRefund.getRefundType());
        log.info("mallOrderPushTypeEnum=" + mallOrderPushTypeEnum);
        if (Objects.nonNull(mallOrderPushTypeEnum)) {
            MallOrderPushDTO mallOrderPushDTO = new MallOrderPushDTO();
            mallOrderPushDTO.setMallOrderRefund(mallOrderRefund);
            mallOrderPushService.mallOrderPushMessage(mallOrderPushDTO, mallOrderPushTypeEnum);
        }
        log.info("推送消息 结束");
        //endregion
    }

    private void paySuccess(MallOrder order, PayMethodEnum paymentMethod, MallPayOrderRecord payOrder) {
        //修改订单
        order.setPayTime(DateTime.now());
        order.setPayType(paymentMethod);
        order.setPayPrice(payOrder.getPayAmount());
        order.updateById();
        if (order.getIsVirtual()) {
            mallOrderService.updateStatusById(order.getId(), MallOrderStatusEnum.FINISH);
        } else {
            mallOrderService.updateStatusById(order.getId(), MallOrderStatusEnum.WAIT_RECEIPT);
        }
        if (StrUtil.isNotBlank(order.getSupplyOrderNo())) {
            smartSupplyHelper.confirmOrder(order);
        }
        //获取订单商品
        List<MallOrderProduct> orderProdcutList = mallOrderProductService.getListByOrderId(order.getId());
        for (MallOrderProduct mallOrderProduct : orderProdcutList) {
            //4.扣除库存
            Assert.isTrue(mallActivitySpecsService.frozenConsumeStockByIdAndCount(mallOrderProduct.getActivitySpecsId(), mallOrderProduct.getProductNum()), () -> new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER));
        }
        UserInfo user = userInfoDao.getById(order.getUserId());
        //是否使用了折扣券，如果使用的折扣券也不计算收益
        UserCoupons userCoupons = userCouponsDao.getByOrderId(order.getId());
        boolean proportionCoupon = Optional.ofNullable(userCoupons).isPresent() && userCoupons.getCouponsType().getType().equals(CouponsTypeEnum.DISCOUNT_PROPORTION_COUPON.getType());
        if (order.getActivityType() == com.sc.nft.enums.task.ActivityTypeEnum.SALES && !order.getIsVirtual()) {
            try {
                //更新排行榜
                BigDecimal consumptionAmount = order.getPayPrice().subtract(order.getWishBalancePrice());
                if (consumptionAmount.compareTo(BigDecimal.ZERO) > 0) {
                    mallUserActivityRankingDetailService.saveOrUpdate(order.getUserId(), null, consumptionAmount, order.getPayTime());
                    //道具释放活动
                    mallUserPropsRewardsDetailService.payScuuess(order.getUserId(), order.getDaoId(), orderProdcutList, payOrder.getPayAmount(), order.getOrderNo(), order.getTotalNum());
                }
            } catch (Exception e) {
                log.error("activity ranking detail save or update error", e);
            }
        }
        //计算收益
        if (!order.getIsVirtual() && !proportionCoupon) {
            mallOrderIncomeService.newCalCulateIncome(orderProdcutList, order, user);
            if (Objects.nonNull(order.getShareTeamId())) {
                mallShareTeamOrderService.create(order.getShareTeamId(), order);
            }
        }
        if (order.getIsVirtual()) {
            // 为虚拟商品订单
            ApiOrderDirect apiOrderDirect = apiOrderDirectService.getByOrderId(order.getId());
            if (Objects.nonNull(apiOrderDirect)) {
                try {
                    // 直充下单
                    FuLuOrderDirectDTO fuLuOrderDirectDTO = fuLuHelper.fuLuOrderDirect(FuLuOrderDirectRequest.build(apiOrderDirect.getApiProductId(), apiOrderDirect.getOrderNo(), apiOrderDirect.getApiChargeAccount(), apiOrderDirect.getApiBuyNum()));
                    if (Objects.nonNull(fuLuOrderDirectDTO)) {
                        apiOrderDirect.setApiOrderId(fuLuOrderDirectDTO.getOrderId());
                        apiOrderDirect.setApiOrderState(fuLuOrderDirectDTO.getOrderState());
                        apiOrderDirect.setApiProductName(fuLuOrderDirectDTO.getProductName());
                        apiOrderDirect.updateById();
                    }
                } catch (Exception e) {
                    log.info("直充下单异常:{}", e.getMessage());
                }
            }
        }
    }

    private void checkPayOrder(MallOrder mallOrder, UserInfo user) {
        Assert.notNull(mallOrder, () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));
        Assert.isTrue(DateTime.now().isBefore(mallOrder.getExpiredTime()), () -> new GlobalRunTimeException(ErrorCode.ORDER_STATUS_ERROR));
        Assert.isTrue(mallOrder.getUserId().longValue() == user.getId().longValue(), () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));
        Assert.isTrue(mallOrder.getStatus() == MallOrderStatusEnum.WAIT_PAY, () -> new GlobalRunTimeException(ErrorCode.ORDER_STATUS_ERROR));
        IdcardInfo idcardInfo = idcardInfoDao.getByUserIdAndIsPass(user.getId());
        Assert.notNull(idcardInfo, () -> new GlobalRunTimeException(ErrorCode.USER_NOT_SM));
        Assert.isNull(mallPayOrderRecordService.getPaySuccessByOrderNo(mallOrder.getOrderNo()), () -> new GlobalRunTimeException(ErrorCode.ORDER_PAID));
    }


    public Map<String, String> analyticalParameters(String params) {
        if (StrUtil.isNotBlank(params)) {
            Map<String, String> paramsMap = Maps.newHashMap();
            for (String str : params.split("&")) {
                String[] s = str.split("=");
                if (s.length == 2) {
                    paramsMap.put(s[0], s[1]);
                } else {
                    paramsMap.put(s[0], StrUtil.EMPTY);
                }
            }
            return paramsMap;
        }
        return null;
    }
}


